package me.seu.demo.test.file;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * 文件切割工具
 * 按照保单节点PolicyInfo切割为小文件
 *
 * @author liangfeihu
 * @since 2020/12/3 上午10:29
 */
@Slf4j
public class FileCutting {

    /**
     * 切割小文件的前缀文件名
     */
    private static final String fileName = "Out_SGE121110000000105_";
    /**
     * 切割后小文件存放目录
     */
    private static final String directoryPath = "/Users/liangfeihu/Documents/work_project/bq/2021_big/105";
    /**
     * 待切割的文件
     */
    private static final String filePath = "/Users/liangfeihu/Documents/work_project/bq/2021_big/Out_SGE121110000000105_20210120100027.xml";

    /**
     * 切割开始与结束标签
     */
    private static final String startStr = "<PolicyInfo>";
    private static final String endStr = "</PolicyInfo>";

    public static void main(String[] args) {
        File sourceFile = new File(filePath);
        // 切分开始
        splitDataToSaveFile(sourceFile, directoryPath);
    }

    public static void splitDataToSaveFile(File sourceFile, String targetDirectoryPath) {
        long startTime = System.currentTimeMillis();
        log.info("开始分割文件");
        StringBuilder endBuilder = new StringBuilder();
        endBuilder.append("</PolicyInfoList>").append("\r\n").append("</TransInfo>").append("\r\n");

        File targetFile = new File(targetDirectoryPath);
        // 检测原文件
        if (!sourceFile.exists() || sourceFile.isDirectory()) {
            return;
        }
        // 检测目录
        if (targetFile.exists()) {
            if (!targetFile.isDirectory()) {
                return;
            }
        } else {
            targetFile.mkdirs();
        }

        try (FileInputStream fileInputStream = new FileInputStream(sourceFile);
             InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
             BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
            // xml 头部 str
            StringBuilder headerBuilder = new StringBuilder();
            String lineStr = null;
            while ((lineStr = bufferedReader.readLine()) != null) {
                headerBuilder.append(lineStr).append("\r\n");
                if (lineStr.contains(startStr)) {
                    // xml头部 构建完成
                    break;
                }
            } // end while

            int fileNum = 1;
            StringBuilder contentBuilder = new StringBuilder();
            while ((lineStr = bufferedReader.readLine()) != null) {
                if (lineStr.contains(startStr)) {
                    // 切分为下一个文件
                    fileNum++;
                    contentBuilder.delete(0, contentBuilder.length());
                    continue;
                }

                // 构建 xml body
                contentBuilder.append(lineStr).append("\r\n");
                if (lineStr.contains(endStr)) {
                    // 开始写入文件
                    String tempName = targetDirectoryPath + File.separator + fileName + fileNum + ".xml";
                    log.info("开始写入第{}个文件，name={}", fileNum, tempName);
                    File file = new File(tempName);
                    writeFile(headerBuilder.toString(), contentBuilder.toString(), endBuilder.toString(), file);
                }
            } // end while

        } catch (Exception e) {
            log.error("分割文件异常", e);
        }

        long endTime = System.currentTimeMillis();
        log.info("分割文件结束，耗时：{}秒", (endTime - startTime) / 1000);
    }

    private static void writeFile(String header, String body, String endStr, File file) {
        try (
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
                BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter, 1024)
        ) {
            bufferedWriter.write(header);
            bufferedWriter.write(body);
            bufferedWriter.write(endStr);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
